package dk.rafaelcouto.PhoneTone_Extractor;

public class Complex
{
    private final double im;
    private final double re;
    
    public Complex() {
        this.re = 0.0;
        this.im = 0.0;
    }
    
    public Complex(final double re) {
        this.re = re;
        this.im = 0.0;
    }
    
    public Complex(final double re, final double im) {
        this.re = re;
        this.im = im;
    }
    
    public Complex(final int n) {
        this.re = n;
        this.im = 0.0;
    }
    
    public Complex(final short n) {
        this.re = n;
        this.im = 0.0;
    }
    
    public static Complex plus(final Complex complex, final Complex complex2) {
        return new Complex(complex.re + complex2.re, complex.im + complex2.im);
    }
    
    public static Complex plus(final short n, final Complex complex) {
        return new Complex(n + complex.re, complex.im);
    }
    
    public double abs() {
        return Math.hypot(this.re, this.im);
    }
    
    public Complex conjugate() {
        return new Complex(this.re, -this.im);
    }
    
    public Complex cos() {
        return new Complex(Math.cos(this.re) * Math.cosh(this.im), -Math.sin(this.re) * Math.sinh(this.im));
    }
    
    public Complex divides(final Complex complex) {
        return this.times(complex.reciprocal());
    }
    
    public Complex exp() {
        return new Complex(Math.exp(this.re) * Math.cos(this.im), Math.exp(this.re) * Math.sin(this.im));
    }
    
    public double im() {
        return this.im;
    }
    
    public Complex minus(final Complex complex) {
        return new Complex(this.re - complex.re, this.im - complex.im);
    }
    
    public double phase() {
        return Math.atan2(this.im, this.re);
    }
    
    public Complex plus(final Complex complex) {
        return new Complex(this.re + complex.re, this.im + complex.im);
    }
    
    public double re() {
        return this.re;
    }
    
    public Complex reciprocal() {
        final double n = this.re * this.re + this.im * this.im;
        return new Complex(this.re / n, -this.im / n);
    }
    
    public Complex sin() {
        return new Complex(Math.sin(this.re) * Math.cosh(this.im), Math.cos(this.re) * Math.sinh(this.im));
    }
    
    public Complex tan() {
        return this.sin().divides(this.cos());
    }
    
    public Complex times(final double n) {
        return new Complex(n * this.re, n * this.im);
    }
    
    public Complex times(final Complex complex) {
        return new Complex(this.re * complex.re - this.im * complex.im, this.re * complex.im + this.im * complex.re);
    }
    
    @Override
    public String toString() {
        if (this.im == 0.0) {
            return new StringBuilder(String.valueOf(this.re)).toString();
        }
        if (this.re == 0.0) {
            return String.valueOf(this.im) + "i";
        }
        if (this.im < 0.0) {
            return String.valueOf(this.re) + " - " + -this.im + "i";
        }
        return String.valueOf(this.re) + " + " + this.im + "i";
    }
}
